﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using JKF.Substructure;
using JKF.Web.smsAPI;
using System.Xml;

namespace JKF.Web
{
    public class SMSHelper
    {
        #region private Fields
        private static SmsAPIPortTypeClient smsClient = new SmsAPIPortTypeClient();
        private static int MaxMobilePerCall = 200;//每次请求最多多少个号码
        #endregion

        #region 通道使用

        /// <summary>
        /// 发送SMS短消息,自动处理>300个号码,如果中途出现错误
        /// 则返回已经发送的条目以及相关错误信息
        /// </summary>
        /// <param name="desNum"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        ///[Obsolete("后台处理程序调用此方法，其他使用请调用SendSMS方法。", false)]
        public static SendMsgResult SendSms2Provider(string desNum, string msg, string account, string pwd)
        {
            try
            {
                string msresult;
                smsClient = smsClient ?? new SmsAPIPortTypeClient();
                //发送短信
                var mbList = new List<string>(desNum.Split(','));
                if (mbList.Count <= MaxMobilePerCall)
                {
                    msresult = smsClient.SendMessage(account, pwd, desNum, msg, "");
                    return AnalyzeSMSResult(msresult);
                }
                var tmpRound = (mbList.Count % MaxMobilePerCall) > 0 ? mbList.Count / MaxMobilePerCall + 1 : mbList.Count / MaxMobilePerCall;
                var tmpCount = 0;
                var tmpBig = mbList.Count % MaxMobilePerCall;
                var tmpresult = new SendMsgResult();
                for (var i = 0; i < tmpRound; i++)
                {
                    msresult = smsClient.SendMessage(
                        account,
                        pwd,
                        string.Join(",", ((i < (tmpRound - 1)) ? mbList.GetRange(i * MaxMobilePerCall, MaxMobilePerCall) : mbList.GetRange(i * MaxMobilePerCall, tmpBig)).ToArray()),
                        msg,
                        ""
                        );

                    tmpresult = AnalyzeSMSResult(msresult);
                    if (null != tmpresult && tmpresult.v_return == 0)
                    {
                        tmpCount += tmpresult.tt_msgs;
                    }
                    else
                    {
                        if (tmpCount > 0)
                        {
                            if (tmpresult == null)
                            {
                                tmpresult = new SendMsgResult { tt_msgs = tmpCount, Info = "发送超过" + MaxMobilePerCall + "个号码中途出现错误." };
                            }
                            else
                            {
                                tmpresult.tt_msgs = tmpCount;
                            }
                            mbList = null;
                            return tmpresult;
                        }
                        return tmpresult;
                    }
                }
                tmpresult.tt_msgs = tmpCount;
                return tmpresult;
            }
            catch (Exception e)
            {
                AppLogger.Log("SendSms2Provider", e);
                return null;
            }
        }

        /// <summary>
        /// 解析短信发送状态信息.
        /// </summary>
        /// <param name="sendRef"></param>
        private static SendMsgResult AnalyzeSMSResult(string sendRef)
        {
            int tmpInt = 0;
            SendMsgResult mresult = new SendMsgResult();
            try
            {
                XmlDocument xd = new XmlDocument();
                xd.LoadXml(sendRef);
                XmlNode root = xd.SelectSingleNode("/").FirstChild;
                mresult.Info = root.Attributes["info"].Value;
                mresult.v_return = int.TryParse(root.Attributes["return"].Value, out tmpInt) ? tmpInt : 0;
                if (mresult.v_return == 0)
                    mresult.tt_msgs = int.TryParse(root.Attributes["messages"].Value, out tmpInt) ? tmpInt : 0;
                else
                    mresult.tt_msgs = 0;
                /*if (mresult.v_return == "0")
                {
                    root = xd.SelectSingleNode("/yd");
                    mresult.yd_Numbers = root.Attributes["numbers"].Value;
                    mresult.yd_Msgs = root.Attributes["messages"].Value;

                    root = xd.SelectSingleNode("/yd");
                    mresult.lt_Numbers = root.Attributes["numbers"].Value;
                    mresult.lt_Msgs = root.Attributes["messages"].Value;

                    root = xd.SelectSingleNode("/yd");
                    mresult.xlt_Numbers = root.Attributes["numbers"].Value;
                    mresult.xlt_Msgs = root.Attributes["messages"].Value;

                }
                */
                xd = null;
                root = null;
                return mresult;
            }
            catch (Exception e)
            {
                AppLogger.Log("解析短信发送结果失败", e);
                return null;
            }

        }

        /// <summary>
        /// 查询当前短信接口状态信息
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        [Obsolete("仅供系统时候，用户代码尽量不要调用", false)]
        public static P_SMSAccountInfo GetSmsProviderInfo(string account, string pwd)
        {
            try
            {
                smsClient = smsClient ?? new SmsAPIPortTypeClient();
                var infos = smsClient.QueryUserInfo(account, pwd);
                var xd = new XmlDocument();
                xd.LoadXml(infos);
                var root = xd.SelectSingleNode("/").FirstChild;
                var accinfo = new P_SMSAccountInfo();
                accinfo.state = int.Parse(root.Attributes["return"].Value);
                accinfo.msg = root.Attributes["info"].Value;
                foreach (XmlNode xn in root.ChildNodes)
                {
                    if (xn.Name == "NAME") { accinfo.Name = xn.InnerText; continue; }
                    if (xn.Name == "UTYPE") { accinfo.UTYPE = int.Parse(xn.InnerText); continue; }
                    if (xn.Name == "SIGN") { accinfo.SIGN = xn.InnerText; continue; }
                    if (xn.Name == "RICHES") { accinfo.RICHES = int.Parse(xn.InnerText); continue; }
                    if (xn.Name == "TOTALIN") { accinfo.TOTALIN = double.Parse(xn.InnerText); continue; }
                    if (xn.Name == "TOTALOUT") { accinfo.TOTALOUT = int.Parse(xn.InnerText); continue; }
                    if (xn.Name == "TOTALSEND") { accinfo.TOTALSEND = int.Parse(xn.InnerText); continue; }
                    if (xn.Name == "CREATETIME") { accinfo.CREATETIME = xn.InnerText; continue; }
                    if (xn.Name == "maxchars_yd") { accinfo.maxchars_yd = int.Parse(xn.InnerText); continue; }
                    if (xn.Name == "maxchars_lt") { accinfo.maxchars_lt = int.Parse(xn.InnerText); continue; }
                    if (xn.Name == "maxchars_xlt") { accinfo.maxchars_xlt = int.Parse(xn.InnerText); continue; }
                }
                xd = null;
                return (accinfo.state == 0) ? accinfo : null;
            }
            catch (Exception e)
            {
                AppLogger.Log("GetSmsProviderInfo", e);
                return null;
            }
        }
        #endregion

        #region Function
        /// <summary>
        /// 计算本次发送短信条目
        /// </summary>
        /// <param name="smsLength"></param>
        /// <param name="mobileLst"></param>
        /// <param name="maxWords">yd,lt,xlt</param>
        /// <returns></returns>
        public static int CalSmsTotalCount(int smsLength, List<string> mobileLst)
        {
            string[] smsmax = SMSMxWords;
            int ydmax = 0, ltmax = 0, xltmax = 0, ydCount = 0, ltCount = 0, xltCount = 0;
            if (smsmax.Length == 3)
            {
                ydmax = (int.TryParse(smsmax[0], out ydmax)) ? ydmax : 70;
                ltmax = (int.TryParse(smsmax[1], out ltmax)) ? ltmax : 70;
                xltmax = (int.TryParse(smsmax[2], out xltmax)) ? xltmax : 70;
            }
            var ydMobileCount = mobileLst.Count(IsChinaMobile);
            var ltMobileCount = mobileLst.Count(IsChinaUnion);
            var xltMobileCount = mobileLst.Count - ydMobileCount - ltMobileCount;
            ydCount = smsLength % ydmax;
            ltCount = smsLength % ltmax;
            xltCount = smsLength % xltmax;
            ydCount = ydCount > 0 ? (smsLength + (ydmax - ydCount)) / ydmax : smsLength / ydmax;
            ltCount = ltCount > 0 ? (smsLength + (ltmax - ltCount)) / ltmax : smsLength / ltmax;
            xltCount = xltCount > 0 ? (smsLength + (xltmax - xltCount)) / xltmax : smsLength / xltmax;

            return ydCount * ydMobileCount + ltCount * ltMobileCount + xltCount * xltMobileCount;
        }
        #endregion

        #region SubClass
        public class P_SMSAccountInfo
        {
            public string Name { get; set; }
            public int UTYPE { get; set; }
            public int RICHES { get; set; }
            public double TOTALIN { get; set; }
            public double TOTALOUT { get; set; }
            public int TOTALSEND { get; set; }
            public string SIGN { get; set; }
            public string CREATETIME { get; set; }
            public int maxchars_yd { get; set; }
            public int maxchars_lt { get; set; }
            public int maxchars_xlt { get; set; }
            public int state { get; set; }
            public string msg { get; set; }
            /*
            <root return="0" info="成功">
              <NAME>{账户名}</NAME>
              <UTYPE>{账户类型:1代理,2集团,3短信}</UTYPE>
              <SIGN>{短信签名}</SIGN>
              <RICHES>{账户条数}</RICHES>
              <TOTALIN>{累计充入}</TOTALIN>
              <TOTALOUT>{累计充出}</TOTALOUT>
              <TOTALSEND>{累计发送}</TOTALSEND>
              <CREATETIME>{创建时间}</CREATETIME>
              <maxchars_yd>{移动单条字符数}</maxchars_yd>
              <maxchars_lt>{联通单条字符数}</maxchars_lt>
              <maxchars_xlt>{小灵通单条字符数}</maxchars_xlt>
            </root>
            */
        }

        public class SendMsgResult
        {
            public int tt_msgs { get; set; }
            public int v_return { get; set; }
            public string Info { get; set; }
            public string yd_Numbers { get; set; }
            public string lt_Numbers { get; set; }
            public string xlt_Numbers { get; set; }
            public string yd_Msgs { get; set; }
            public string lt_Msgs { get; set; }
            public string xlt_Msgs { get; set; }
        }
        #endregion

        #region Validate
        //短信平台支持的手机号码
        private static List<string> allNum = new List<string>("134,135,136,137,138,139,150,151,152,158,159,157,188,130,131,132,155,156,133,153,189".Split(','));
        private static List<string> ydNum = new List<string>("134,135,136,137,138,139,150,151,152,158,159,157,188,186".Split(','));//移动号码
        private static List<string> ltNum = new List<string>("130,131,132,155,156,133,153,189".Split(','));//联通号码
        private static string[] SMSMxWords = new string[] { "70", "70", "56" };
        /// <summary>
        /// 是否为合法的手机号码
        /// </summary>
        /// <param name="mobileNo"></param>
        /// <returns></returns>
        public static bool IsValidMobileNo(string mobileNo)
        {
            return Regex.IsMatch(mobileNo, @"^1[358]\d{9}$", RegexOptions.IgnoreCase) && allNum.Contains(mobileNo.Substring(0, 3));
        }

        /// <summary>
        /// 是否是移动号码
        /// </summary>
        /// <param name="mobileNo"></param>
        /// <returns></returns>
        public static bool IsChinaMobile(string mobileNo)
        {
            return ydNum.Contains(mobileNo.Substring(0, 3));
        }

        /// <summary>
        /// 是否是联通的号码
        /// </summary>
        /// <param name="mobileNo"></param>
        /// <returns></returns>
        public static bool IsChinaUnion(string mobileNo)
        {
            return ltNum.Contains(mobileNo.Substring(0, 3));
        }

        /// <summary>
        /// 是否是小灵通
        /// </summary>
        /// <param name="mobileNo"></param>
        /// <returns></returns>
        public static bool IsXiaoLT(string mobileNo)
        {
            return false;
        }

        /// <summary>
        /// 验证手机号码，将错误的手机号码分离出来,
        /// 并Select Distinct Mobile Numbers
        /// </summary>
        /// <param name="mobilelst"></param>
        /// <param name="invalidNos"></param>
        public static void ValidateMobileNo(ref List<string> mobilelst, ref List<string> invalidNos)
        {
            invalidNos = mobilelst.Where(a => (!IsValidMobileNo(a))).ToList();
            mobilelst = mobilelst.Where(a => (IsValidMobileNo(a))).ToList();
            //Remove Redundance Items
            mobilelst = (new HashSet<string>(mobilelst.ToArray()).ToList());
        }

        /// <summary>
        /// 是否是可被发送的手机号码
        /// </summary>
        /// <param name="mobileNos"></param>
        /// <returns></returns>
        public static bool IsAllowBySys(string mobileNo)
        {
            if (IsValidMobileNo(mobileNo))
            {
                return ((IsChinaMobile(mobileNo)) || IsChinaUnion(mobileNo) || IsXiaoLT(mobileNo));
            }
            return false;
        }
        #endregion
    }
}
